/*
 * Copyright (c) 2008 Ricardo Rocha, rocha.porto@gmail.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.gliding.kumulus.client.model;

import java.util.ArrayList;
import java.util.Date;

import org.gliding.kumulus.client.Calendar;
import org.gliding.kumulus.client.CalendarEventListener;
import org.gliding.kumulus.client.Kumulus;

/**
 * Definition of a PlanningContext object.
 * 
 * It contains all the model data of the Planning application, including the existing members,
 * the active day summaries that should be shown in the interface, the current login session
 * (if there is one), etc.
 * 
 * @author Ricardo Rocha <rocha.porto@gmail.com>
 * @version $Rev:: $
 */
public class PlanningContext implements CalendarEventListener {

    private static PlanningContext singleton;
    
    private ArrayList updateListeners = new ArrayList();
    
	/**
	 * The list of currently active member roles.
	 */
	private String[] activeMemberRoles = new String[] {"INSTRUCTOR", "STUDENT", "PILOT", "WINCHDRIVER", "TOWPILOT"};
	
	/**
	 * The list of currently active activity day summaries.
	 */
	private ActivityDaySummary[] activeDaySummaries;
	
	/**
	 * The list of members.
	 */
	private Member[] members;
	
	/**
	 * Class constructor.
	 */
	private PlanningContext() {
		
	}
	
	/**
	 * Returns a list containing the currently active activity days.
	 * 
	 * @return A list containing the currently active activity days
	 */
	public ActivityDaySummary[] getActiveDaySummaries() {
		return activeDaySummaries;
	}
	
	/**
	 * Returns the list of currently active member roles.
	 * 
	 * This is usually fetched when the application is loaded.
	 * 
	 * @return The list of currently active roles
	 */
	public String[] getActiveMemberRoles() {
		return this.activeMemberRoles; 
	}
	
	/**
	 * Replaces the currently active activity days with the ones corresponding to the given
	 * date period.
	 * 
	 * If necessary it will communicate to the remote server to fetch the activity data for
	 * the requested days.
	 * 
	 * @param startDate The first activity day to be set active
	 * @param endDate The last activity day to be set active
	 */
	public void updateActiveDaySummaries(Date startDate, Date endDate) {
		
        Kumulus.setMessage("Updating summary data...");
        
        int numberDays = (int)((endDate.getTime() - startDate.getTime()) / (long)86400000) + 1;
        
		activeDaySummaries = new ActivityDaySummary[numberDays];
		
		Member[] pilots = new Member[] { new Member(1, "Ricardo", "Rocha", "rocha.porto@gmail.com"),
				new Member(2, "Faye", "Riegel", "riegel.faye@wanadoo.fr") };
		
		Member[] instructors = new Member[] { new Member(3, "Michel", "Alloin", "michel.alloin@wanadoo.fr"),
				new Member(3, "Michel", "Alloin", "michel.alloin@wanadoo.fr") };
		
		Member[] students = new Member[] { new Member(1, "Ricardo", "Rocha", "rocha.porto@gmail.com"),
				new Member(2, "Faye", "Riegel", "riegel.faye@wanadoo.fr"),
				new Member(6, "Jack", "Riegel", "riegel.jack@wanadoo.fr"),
				new Member(7, "Emilie", "Stilmant", "riegel.jack@wanadoo.fr"),
				new Member(8, "Jeremy", "Sauron", "riegel.jack@wanadoo.fr"),
				new Member(9, "Romain", "Fert", "riegel.jack@wanadoo.fr")};
		
		Member[] winchDrivers = new Member[] { new Member(7, "Emilie", "Stilmant", "rocha.porto@gmail.com"),
				new Member(2, "Faye", "Riegel", "riegel.faye@wanadoo.fr") };
		
		for (int i=0; i<activeDaySummaries.length; i++) {
			Date tmpDate = new Date(startDate.getTime() + (i * (long)86400000));
			
			activeDaySummaries[i] = new ActivityDaySummary(tmpDate);
			
			activeDaySummaries[i].updateActivity("INSTRUCTOR", ActivityDaySummary.MORNING, instructors);
			activeDaySummaries[i].updateActivity("STUDENT", ActivityDaySummary.MORNING, students);
			activeDaySummaries[i].updateActivity("PILOT", ActivityDaySummary.MORNING, pilots);
			activeDaySummaries[i].updateActivity("WINCHDRIVER", ActivityDaySummary.MORNING, winchDrivers);
			
			activeDaySummaries[i].updateActivity("INSTRUCTOR", ActivityDaySummary.AFTERNOON, instructors);
			activeDaySummaries[i].updateActivity("STUDENT", ActivityDaySummary.AFTERNOON, students);
			activeDaySummaries[i].updateActivity("PILOT", ActivityDaySummary.AFTERNOON, pilots);
			activeDaySummaries[i].updateActivity("WINCHDRIVER", ActivityDaySummary.AFTERNOON, winchDrivers);
		}
		
        Kumulus.setMessage("");
        

        // Trigger the listeners update
        for (int i=0; i<this.updateListeners.size(); i++) {
            ((PlanningContextUpdateListener)this.updateListeners.get(i)).onDateUpdate(this);
        }
	}
	
    /**
     * Removes the given activity entry.
     * 
     * @param date The date of the activity that should be removed
     * @param role The role the member should be removed from
     * @param partOfDay The part of the day where the entry should be removed
     * @param memberID The ID of the member corresponding to the activity being removed
     */
	public void removeMemberActivity(Date date, String role, int partOfDay, int memberID) {
		for (int i=0; i<activeDaySummaries.length; i++) {
			if (activeDaySummaries[i].getDate() == date) {
				activeDaySummaries[i].removeActivityEntry(role, partOfDay, memberID);
			}
		}
        // Trigger the listeners update
        for (int i=0; i<this.updateListeners.size(); i++) {
            ((PlanningContextUpdateListener)this.updateListeners.get(i)).onEntryRemoval(this);
        }		
	}

    /**
     * @see CalendarEventListener.onDateUpdate(Calendar w)
     */
    public void onDateUpdate(Calendar w) {
        Date[] selectedDates = w.getDatesSelected();
        updateActiveDaySummaries(selectedDates[0], selectedDates[selectedDates.length-1]);
    }

    /**
     * Static method returning the singleton object.
     * 
     * @return A PlanningContext singleton
     */
    public static PlanningContext getPlanningContext() {
        if (singleton == null) {
            PlanningContext.singleton = new PlanningContext();
        }
        return singleton;
    } 
    
    /**
     * Adds the given object as a listener to events on this PlanningContext.
     * 
     * @param listener The object that should react to events on this PlanningContext
     */
    public void addPlanningContextUpdateListener(PlanningContextUpdateListener listener) {
        this.updateListeners.add(listener);
        listener.onDateUpdate(this);
    }
}
